// 光线交互
import type { Attenuation, Material } from "./materialUtil"
import type { Ray } from "./rayUtil"
import { Vec3 } from "./vectorUtil"

/**
 * 一个对象是否可以交互的接口
 */
export interface Hitable {
  /** 几何体id */
  id?: string
  /** 可选的材质属性 */
  material?: Material

  /**
   * 交互的函数
   * @param ray 光线
   * @param t_min 最小时间
   * @param t_max 最大时间
   * @returns 
   */
  hit: (
    ray: Ray,
    t_min: number,
    t_max: number
  ) =>
    HitResult | null
}

/**
 * 交互记录
 */
export class HitRecord {
  /** 几何体id */
  id?: string
  /** 交互时间 */
  time: number
  /** 交互点 */
  point: Vec3
  /** 法线 */
  normal: Vec3
  constructor(
    time: number = 0,
    point: Vec3 = new Vec3(0, 0, 0),
    normal: Vec3 = new Vec3(0, 0, 0)) {

    this.time = time
    this.point = point
    this.normal = normal
  }
}

/**
 * 交互列表，取t值最小的，具有遮挡效果
 */
export class HitList implements Hitable {

  /** 可交互的几何体集合 */
  hitableList: Hitable[]

  constructor(list: Hitable[]) {
    this.hitableList = list
  }

  /** 遍历交互列表得到最短的t */
  hit(ray: Ray, t_min: number, t_max: number): HitResult | null {
    let closest_t = t_max
    let hitResult: HitResult | null = null
    for (let hitable of this.hitableList) {
      let tmpHitResult = hitable.hit(ray, t_min, t_max)
      if (tmpHitResult && (tmpHitResult.hit.time < closest_t)) {
        hitResult = tmpHitResult
        closest_t = tmpHitResult.hit.time
      }
    }
    return hitResult
  }
}

/** 包含有交互记录和反射光线的结果 */
export interface HitResult {
  /** 交互点 */
  hit: HitRecord,
  /** 反射光线 */
  reflectRay: Ray,
  /** 衰减 */
  attenuation: Attenuation,
  /** 漫反射 */
  isDiffusion: boolean
}
